use std::collections::VecDeque;

fn main() {
    let inputs: Vec<&str> = include_str!("../input.txt").lines().collect();
    part1(&inputs);
}

fn part1(inputs: &[&str]) {
    let decimal_sum = inputs
        .into_iter()
        .map(|s| snafu_to_decimal(s))
        .sum::<i64>();
    println!("Part 1: {}", decimal_to_snafu(decimal_sum));
}

fn snafu_to_decimal(literal: &str) -> i64 {
    let mut k = 1;
    let mut result = 0;
    for token in literal.chars().rev() {
        let digit = match token {
            '0' | '1' | '2' => token as i64 - '0' as i64,
            '-' => -1,
            '=' => -2,
            _ => panic!("Bad literal '{}'", literal),
        };
        result += digit * k;
        k *= 5;
    }

    result
}

fn decimal_to_snafu(literal: i64) -> String {
    let mut five_literal = decimal_to_five(literal);
    let len = five_literal.len();
    for i in (0..len).into_iter().rev() {
        match five_literal[i] {
            0 | 1 | 2 => continue,
            3 | 4 => {
                // cur idx mean five_literal[cur_idx] need to change -2;
                let mut cur_idx = i;
                loop {
                    five_literal[cur_idx] = -2;
                    // is last one
                    if cur_idx == five_literal.len() - 1 {
                        five_literal.push_back(1);
                        break;
                    }
                    // last should add 1
                    five_literal[cur_idx + 1] += 1;
                    if five_literal[cur_idx + 1] == 3 {
                        cur_idx += 1;
                        continue;
                    } else {
                        break;
                    }
                }

                if five_literal[i] == 4 {
                    five_literal[cur_idx] = -1;
                }
            },
            _ => panic!(),
        }
    }

    five_literal
        .into_iter()
        .rev()
        .map(|d| -> char {
            match d {
                0 => '0',
                1 => '1',
                2 => '2',
                -1 => '-',
                -2 => '=',
                _ => panic!(),
            }
        })
        .collect()
}

fn decimal_to_five(literal: i64) -> VecDeque<i64> {
    let mut k = 5;
    let mut len = 1;
    while literal > k {
        len += 1;
        k *= 5;
    }

    let mut literal = literal;
    k /= 5;
    let mut five_literal = VecDeque::new();
    for _ in 0..len {
        let res = literal / k;
        let reminder = literal % k;
        five_literal.push_front(res);
        literal = reminder;
        k /= 5;
    }

    five_literal
}

/*

    0 1 2 3 4 
    = - 0 1 2

   -2 => =
   -1 => -
    0 => 0
    1 => 1
    2 => 2
    3 => 1=
    4 => 1-
    5 => 10
    6 => 11
    7 => 12
    8 => 2=
    9 => 2-
    10 => 20
    11 => 21 

    4890 => 4892 => 

    3125 625 125 25 5 1

    124032
    2=-1=2

    345 => 2340

    ['2', '3', '4', '0']

    i = 3:
    2 in ['0', '1', '2', '-', '='], pass

    i = 2
    3 not in ['0', '1', '2', '-', '=']
    3 => '='
    so, s[3] add 1 => '2' => '3' => '=', add s[4] = 1

    ['1', '=', '=', '4', '0']

    i = 1
    4 not in ['0', '1', '2', '-', '=']
    4 => '=' 
    so, s[2] add 1 => '=' => '-'

    ['1', '=', '-', '-', '0']

    i = 0
    0 in ['0', '1', '2', '-', '='], pass

    => ['1', '=', '-', '-', '0']

*/